<?php

namespace YouBaoLian\Common;

use Exception;
use YouBaoLian\Application\Callback\CallbackRequest;
use YouBaoLian\Config\Config;
use YouBaoLian\Http\Response;
use YouBaoLian\Application\Request\Request;

class Base
{

    /**
     * @var Config $config
     */
    protected $config;

    /**
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    protected function execute(Request $request)
    {

        $encrypt = new Encrypt($this->config);

        $requestParamOrg = [
            'appId' => $this->config->getAppId(),
            'requestId' => sha1(uniqid()),
            'version' => '1.0',
            'method' => $request->getMethod(),
            'bizContent' => json_encode($request->getBizContent(), JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
            'requestTime' => date('Y-m-d H:i:s'),
            'format' => 'json',
            'signType' => 'RSA2',
            'charset' => 'UTF-8'
        ];

        $requestParam = $this->sign($encrypt, $requestParamOrg);

        $response = $this->request($requestParam, $request->getResponse(), $requestParamOrg);

        if ($response->isSuccess()) {
            try {
                $bizContent = $this->checkSign($encrypt, $response->getBody());

                //----
//                $ttlog =  '{"bizContent":{"resultCode":0,"message":null,"supplierId":null,"channelId":7508,"epolicyLink":"xxxx/chexian/electronicInsurance/9811/20054/9811_2111503562021016913_10.PDF","ciFlagLink":null},"code":0,"message":"success","requestId":"c5951f03dbc778b68da2eb5d21e6e84d2aa459ac","responseTime":"2022-05-27 11:03:21","sign":"FDSIJpVkklSDwqXS5Y+63w5mlQBMv8CR6CKga89e2ObSGC6edqWJ88f8ODkYFYTYqonnV8LJ+mK4s8n3IRWiu+Fb1llN6vS9cqUO5kbtz3BYUWWgto4nsmzZ4zA6iBl5deMPCcJKMx0\/YTPXlXm+YzTo8ZCr3Yz4AgSyX1SQiHcpH71iDRT\/vga9hyU4IvSHQ1AbM7CBLSn5BwLLuTx37xX+d2zKWRFfmLGRbxMGiPB5qPPHix3ZvAYV+bu8WxG4aN\/rlW7jjrfqfd9PSyL2WV6BzaaiDVGqzeD34mr8Wp6FkhbGRwHLDuIHP\/KvsNOJKJ85PMa3VqGdXaEzjvhTuA=="}';
//                $bizContent= json_decode($ttlog,true);
//                var_dump($bizContent);
                //-----

                $response->setBizContent($bizContent['bizContent']);

                $response->responseLogs($bizContent);

                $response->build();

            } catch (Exception $exception) {
                $response->setCode(505);
                $response->setError($exception->getMessage());
            }
        }
        return $response;
    }

    /**
     * 签名生成 包括 bizContent  sign
     * @param Encrypt $encrypt
     * @param array $param
     * @return array
     * @throws Exception
     */
    private function sign(Encrypt $encrypt, array $param): array

    {
        $encrypt->setEncryptParams($param);
        $encrypt->bizEncrypt();
        $encrypt->sign();

        return $encrypt->getEncryptParams();
    }

    /**
     * @param CallbackRequest $callbackRequest
     * @return void
     */
    public function verifySign(CallbackRequest $callbackRequest)
    {
        $encrypt = new Encrypt($this->config);

        try {

            $bizContent = $this->checkSign($encrypt, $callbackRequest->getBody());
            $callbackRequest->setBizContent($bizContent['bizContent']);
            $callbackRequest->construe();

        } catch (Exception $e) {
            $callbackRequest->setError($e->getMessage());
        }
    }

    /**
     * 验证签名
     * @param Encrypt $encrypt
     * @param array $responseData
     * @return void
     * @throws Exception
     */
    private function checkSign(Encrypt $encrypt, array $responseData): array
    {
        $encrypt->setDecryptParams($responseData);
        $encrypt->verify();
        $encrypt->bizDecrypt();

        return $encrypt->getDecryptParams();
    }


    /**
     * @param array $requestParam
     * @param string $response
     * @param array $orgRequestParam
     * @return Response
     */
    private function request(array $requestParam, string $response, array $orgRequestParam): Response
    {
        $request = new \YouBaoLian\Http\Request();
        $request->setUrl($this->config->getGateway());
        $request->setLogsDir($this->config->getLogsDir());
        $request->setMethod('post');
        $request->setHttpErrors(false);
        $request->setJson($requestParam);
        $request->setOrgRequestParam($orgRequestParam);
        $request->setTimeout($this->config->getTimeout());

        return $request->request($response);
    }
}
